package cn.remex.core;

import cn.remex.RemexConstants;
import cn.remex.core.exception.ServiceCode;
import cn.remex.core.util.Assert;
import cn.remex.core.util.RequestHelper;
import cn.remex.core.util.StringHelper;
import cn.remex.db.model.SysUser;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * @author lanchenghao
 * @since 2013-7-23下午7:50:27
 * 系统当前状态变量，如session，用户，线程等
 */
public class CoreSvo {
	public final static ThreadLocal<Map<String, Object>> localParams = new ThreadLocal<Map<String, Object>>();
	public final static String HTTP_REQUEST_KEY = "CORESVO_HTTP_REQUEST";
	public final static String HTTP_RESPONSE_KEY = "CORESVO_HTTP_RESPONSE";
	public final static String HTTP_COOKIES = "CORESVO_HTTP_COOKIES";
	public final static String HTTP_SESSION = "CORESVO_HTTP_SESSION";
	public final static String HTTP_CLIENT_IP = "CORESVO_HTTP_CLIENT_IP";
	public final static String HTTP_USER_NAME = "CORESVO_HTTP_USER_NAME";

	public final static String HTTP_HEADER_APP_CHANNEL = "CORESVO_HTTP_HEADER_APP_CHANNEL";
	public final static String HTTP_HEADER_APP_VERSION = "CORESVO_HTTP_HEADER_APP_VERSION";

	public static void initHttp(HttpServletRequest request, HttpServletResponse response) {
		putLocal(HTTP_REQUEST_KEY, request);
		putLocal(HTTP_RESPONSE_KEY, response);

		Map<String, Cookie> cookies = new HashMap<>();
		if (null != request.getCookies())
			for (Cookie cookie : request.getCookies()) {
				cookies.put(cookie.getName(), cookie);
			}
		putLocal(HTTP_COOKIES, cookies);
		putLocal(HTTP_SESSION, request.getSession());
		putLocal(HTTP_CLIENT_IP, RequestHelper.getClientIP(request));

		putLocal(HTTP_HEADER_APP_CHANNEL, request.getHeader("channel"));
		putLocal(HTTP_HEADER_APP_VERSION, request.getHeader("appver"));

		SysUser curUser = RemexContext.obtainCurUser();
		if(curUser == null){
			CoreSvo.putLocal(HTTP_USER_NAME, "anonymous");
		}else{
			CoreSvo.putLocal(HTTP_USER_NAME, curUser.getUsername());
		}
	}

	/**
	 * 将值存入当前线程
	 *
	 * @param key   key
	 * @param value value
	 */
	public static void putLocal(String key, Object value) {
		Map<String, Object> map = localParams.get();
		if (null == map) {
			map = new HashMap<>();
			localParams.set(map);
		}

		//	当传入value为null时，执行remove，以防key不删除导致内存泄漏	by xinxinran	20171019
		if(value == null){
			map.remove(key);
		}else {
			map.put(key, value);
		}
	}

	public static void destoryHttp() {
		putLocal(HTTP_REQUEST_KEY, null);
		putLocal(HTTP_RESPONSE_KEY, null);
		putLocal(HTTP_COOKIES, null);
		putLocal(HTTP_SESSION, null);
		putLocal(HTTP_CLIENT_IP, null);
		putLocal(HTTP_USER_NAME, null);
	}

	//session
	public static Object valSession(String key) {
		HttpSession session = (HttpSession) valLocal(HTTP_SESSION);
		Assert.notNull(session, ServiceCode.ERROR, "没有初始化Cookies会话容器，请调用CoreSvo.initHttp()！");
		return session.getAttribute(key);
	}

	/**
	 * 将值从当前线程取出
	 *
	 * @param key key
	 * @return Object
	 */
	public static Object valLocal(String key) {

		Map<String, Object> map = localParams.get();
		if (null == map) {
			map = new HashMap<>();
			localParams.set(map);
		}
		return map.get(key);
	}

	public static void putSession(String key, String value) {
		HttpSession session = (HttpSession) valLocal(HTTP_SESSION);
		Assert.notNull(session, ServiceCode.ERROR, "没有初始化Cookies会话容器，请调用CoreSvo.initHttp()！");
		session.setAttribute(key, value);
	}

	public static String valCookieValue(String key) {
		Cookie cookie = valCookie(key);
		String string = cookie != null ? StringHelper.urlDecode(cookie.getValue(), "UTF-8") : null;
		return string;
	}

	public static Cookie valCookie(String key) {
		if (valLocal(HTTP_REQUEST_KEY) == null) {
			//RemexConstants.logger.debug("在非HTTP环境中获取cookie失败，直接返回null");
			return null;
		}
		Map<String, Cookie> cookies = (Map<String, Cookie>) valLocal(HTTP_COOKIES);
		//Assert.notNull(cookies, ServiceCode.ERROR, "没有初始化Cookies会话容器，请调用CoreSvo.initHttp()！");
		return cookies.get(key);
	}

	/**
	 * 设置cookies
	 * 默认为会话有效期，path 为/
	 *
	 * @param name  name
	 * @param value value
	 */
	public static void putCookie(String name, String value) {
		try {
			String v = value != null ? URLEncoder.encode(value, "UTF-8") : value;
			Cookie cookie = new Cookie(name, v);
			cookie.setPath("/");
			cookie.setVersion(1);

			Map<String, Cookie> cookies = (Map<String, Cookie>) valLocal(HTTP_COOKIES);
			cookies.put(name, cookie);
			putCookie(cookie);
		} catch (UnsupportedEncodingException e) {
			RemexConstants.logger.error("Cookies设置失败！{}", e);
		}
	}

	public static void putCookie(Cookie cookie) {
		HttpServletResponse response = (HttpServletResponse) valLocal(HTTP_RESPONSE_KEY);
		Assert.notNull(response, ServiceCode.ERROR, "没有初始化Cookies会话容器，请调用CoreSvo.initHttp()！");

		Map<String, Cookie> cookies = (Map<String, Cookie>) valLocal(HTTP_COOKIES);
		if (null == cookie.getValue()) { //删除cookie
			cookies.remove(cookie.getName());
			cookie.setMaxAge(0);
			response.addCookie(cookie);
		} else {
			cookies.put(cookie.getName(), cookie);
			response.addCookie(cookie);
		}

	}


}
